package com.sure.minion.services.base.utils;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import com.sure.minion.services.base.vo.PagedResult;

/**
 * @Description 对象转换工具
 * @author sure
 * @date 2015年9月16日  下午4:58:26
 */
public class ConvertUtil {
	
	private static Logger logger = LoggerFactory.getLogger(ConvertUtil.class);
	
	/**
	 * 
	 * @Description 对象克隆
	 * @author mawei
	 * @date 2015-2-6  下午6:44:07
	 * Company: TravelSky
	 */
	public static <K> K beanClone(K sourceObj, Class<K> sourceClass){
		
		if(sourceObj==null){
			return null;
			
		}
		K targetObj = null;
		
		try{
			Constructor<K> voconstructor = sourceClass.getConstructor(new Class[]{});
			targetObj = voconstructor.newInstance(new Object[]{});
			BeanUtils.copyProperties(sourceObj, targetObj);
		}catch (Exception e) {
			logger.error("对象克隆失败",e);
		}
		return targetObj;
	}

	/**
	 * 
	 * @Description 深度克隆
	 * @author mawei
	 * @date 2015-2-6  下午6:44:07
	 * Company: TravelSky
	 */
	@SuppressWarnings("unchecked")
	public static <K> K  depthClone(K sourceObj) {
		
		K targetObj = null;
		
		try {
			ByteArrayOutputStream bo = new ByteArrayOutputStream(); 
            ObjectOutputStream oo = new ObjectOutputStream(bo);
            oo.writeObject(sourceObj);//源对象
            
            ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray()); 
            ObjectInputStream oi= new ObjectInputStream(bi); 
            targetObj = (K) oi.readObject();//目标对象 
		} catch (Exception e) {
			logger.error("深度克隆失败",e);
        } 
		
		return targetObj;
	}

	/**
	 * 	
	 * @Description 把一个列表中的PO类全转换成为相应的VO类的列表，VO类需要有一个以PO类为参数的构造函数
	 * @param sourceList 原PO列表
	 * @param poclass 原始的PO类
	 * @param voclass 需要转换成的VO类
	 * @return 转换成的VO列表
	 * @author mawei
	 * @date 2015-2-6  下午6:45:23
	 */
	public static <K, V> List<V> convertPOListToVOList(List<K> sourceList,Class<K> poclass, Class<V> voclass){
		
		if(sourceList==null){
			return null;
			
		}
		
		List<V> targetList = new ArrayList<V>();
		
		try{
			if(sourceList.size()>0){
				Constructor<V> voconstructor = voclass.getConstructor(new Class[]{poclass});
				
				for(K source:sourceList){			
					V target = voconstructor.newInstance(new Object[]{source});
					targetList.add(target);
				}
			}
		}catch (Exception e) {
			logger.error("转换List失败",e);
		}
		return targetList;
	}
	
	/**
	 * @Description voList 转换为 poList
	 * @param sourceList
	 * @param voclass
	 * @param poclass
	 * @return
	 * @author syuan
	 * @date 2015年9月29日  下午9:09:36
	 */
	@SuppressWarnings("unchecked")
	public static <K, V> List<V> convertVOListToPOList(List<K> sourceList, Class<K> voclass, Class<V> poclass) {

		List<V> returnlist = new ArrayList<V>();
		
		String poname = poclass.getName();
		String shortname = poname.substring(poname.lastIndexOf(".") + 1);
		
		Method[] methods = voclass.getMethods();
		Method targetmethod = null;
		for (Method method : methods) {
			if (shortname.equals(method.getName().replaceAll("to", ""))) {
				targetmethod = method;
				break;
			}
		}
		
		if (targetmethod != null) {
			for (K vo : sourceList) {
				V po = null;
				try {
					po = (V) targetmethod.invoke(vo);
				} catch (Exception e) {
					logger.error("转换List失败",e);
				}
				returnlist.add(po);
			}
		}
		
		return returnlist;
	}
		
	/**
	 * 
	 * @Description 把一个PagedResult列表中的PO类全转换成为相应VO类，VO类需要有一个以PO类为参数的构造函数
	 * @param sourceResult 原PagedResult
	 * @param poclass 原始的PO类
	 * @param voclass 需要转换成的VO类
	 * @return 含转换成的VO类列表PagedResult
	 * @author mawei
	 * @date 2015-2-6  下午6:59:35
	 */
	public static <K, V> PagedResult<V> convertPOResultToVOResult(PagedResult<K> sourceResult,Class<K> poclass, Class<V> voclass){
		
		if(sourceResult == null){
			return null;
		}
		
		PagedResult<V> targetResult = new PagedResult<V>();
		List<V> targetList = ConvertUtil.convertPOListToVOList(sourceResult.getResultList(), poclass, voclass);
		
		targetResult.setResultList(targetList);
		targetResult.setCurrentPage(sourceResult.getCurrentPage());
		targetResult.setNumPerPage(sourceResult.getNumPerPage());
		targetResult.setTotalNum(sourceResult.getTotalNum());
		targetResult.setTotalPage(sourceResult.getTotalPage());
		
		return targetResult;
	}
}
